﻿using System;
using System.Collections;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace LevelUp.Serializer.Test
{
    [TestClass]
    public class SerializerTest
    {
		#region Const
		const string SERIALIZE_FILE_NAME = @"SerializedData.dat";
		#endregion

		[TestMethod]
		[ExpectedException(typeof(ArgumentOutOfRangeException))]
		public void GetSerializer_WithNoneSerializerType_ThrowsArgumentOutOfRangeException()
		{
			Serializer.GetSerializer(SerializerType.None);
		}

    	[TestMethod]
		[ExpectedException(typeof(ArgumentOutOfRangeException))]
		public void GetSerializer_WithWrongSerializerType_ThrowsArgumentOutOfRangeException()
		{
			Serializer.GetSerializer((SerializerType)(Enum.GetNames(typeof(SerializerType)).Length + 1));
		}

    	[TestMethod]
		public void GetSerializer_GetAllSerializer_GetCorrectSerializer()
		{
			foreach (SerializerType type in Enum.GetValues(typeof(SerializerType)))
			{
				if (type == SerializerType.None)
					continue;

				ISerializer serializer = Serializer.GetSerializer(type);

				Assert.IsNotNull(serializer);

				var attribute = type.GetCustomAttribute<RelativedTypeAttribute>();
				Assert.IsNotNull(attribute);
				Assert.IsInstanceOfType(serializer, attribute.Type);
			}
		}

		[TestMethod]
		public void DeSerialize_DeSerializeFromStreamByAllSerializer_DeSerializeSuccess()
		{
			foreach (SerializerType type in Enum.GetValues(typeof(SerializerType)))
			{
				if (type == SerializerType.None)
					continue;
				using (var ms = new MemoryStream())
				{

					ISerializer serializer = Serializer.GetSerializer(type);
					serializer.Serialize(0, ms);

					ms.Seek(0, SeekOrigin.Begin);
					var result = serializer.DeSerialize<int>(ms);
					Assert.AreEqual(0, result);
				}
			}
		}


		[TestMethod]
		public void Serialize_SerializeToStreamByAllSerializer_SerializeSuccess()
		{
			foreach (SerializerType type in Enum.GetValues(typeof(SerializerType)))
			{
				if (type == SerializerType.None)
					continue;
				using (var ms = new MemoryStream())
				{
					ISerializer serializer = Serializer.GetSerializer(type);
					serializer.Serialize(0, ms);
					Assert.AreNotEqual(ms.Length, 0);
				}
			}
		}

		[TestMethod]
		public void Serialize_SerializeToFileByAllSerializer_SerializeSuccess()
		{
			foreach (SerializerType type in Enum.GetValues(typeof(SerializerType)))
			{
				if (type == SerializerType.None)
					continue;

				var obj = new ArrayList { "Larry", "LevelUp", @"http://www.dotblogs.com.tw/larrynung" };

				Serializer.Serialize(obj, SERIALIZE_FILE_NAME, type);

				Assert.IsTrue(File.Exists(SERIALIZE_FILE_NAME), "Serialized file not existed");

				File.Delete(SERIALIZE_FILE_NAME);
			}
		}

		[TestMethod]
		public void DeSerialize_DeSerializeFromFileByAllSerializer_DeSerializeSuccess()
		{
			foreach (SerializerType type in Enum.GetValues(typeof(SerializerType)))
			{
				if (type == SerializerType.None)
					continue;

				//Arrange
				var obj = new ArrayList { "Larry", "LevelUp", @"http://www.dotblogs.com.tw/larrynung" };
				var expectedObj = obj;

				//Act
				Serializer.Serialize(obj, SERIALIZE_FILE_NAME, type);
				var deSerializedObj = Serializer.DeSerialize<ArrayList>(SERIALIZE_FILE_NAME, type);


				//Assert
				for (var idx = 0; idx < expectedObj.Count; ++idx)
				{
					Assert.AreEqual(expectedObj[idx], deSerializedObj[idx]);
				}

				File.Delete(SERIALIZE_FILE_NAME);
			}
		}
    }
}
